
/**
 * Copyright 2010 Victor Egea Hernando
 *
 * RockScript is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * 
 * RockScript is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with RockScript.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "corelib.h"

namespace paper{

/****************************************************************** 
 * corelib.core.Object
 ******************************************************************/


/****************************************************************** 
 * corelib.core.String
 ******************************************************************/

/**************************************************************
 * constructor
 **************************************************************/
corelib::int32 string_cnstr_hnd( paper::vmachine &vm, paper::method &mp, corelib::uint32 pc ){ 
	__register &othis = vm.spreg( REG_TOOGLE(0) );
	__register &reg = vm.spreg( REG_TOOGLE(1) );

	// assign constant string
	((ostring*)regobject( othis ))->set_string( *regstring( reg ) );

	return 1; // pc++
}

void string_cnstr( vm_class &lib_class ){
	corelib::uint32 idx = 0;
	lib_class.get_method_idx( "cnstr_1_", idx );
	method *m_string_cnstr = lib_class.get_method( idx );

	// allocate memory
	if(	!m_string_cnstr->set_stack_frame_size( 0, 0 ) ){
		std::cout << "error allocating string constructor memory" << std::endl;
		return;
	}

	m_string_cnstr->set_flags( paper::FLG_MTHD_STATIC );
	m_string_cnstr->set_cpp_handler( &string_cnstr_hnd );
	m_string_cnstr->add_inst_b(paper::OP_CPPCODE,0,0);
	m_string_cnstr->add_inst_b(paper::OP_RETURN,10,0);
}

/**************************************************************
 * operand addition
 **************************************************************/
corelib::int32 string_addition_hnd( paper::vmachine &vm, paper::method &mp, corelib::uint32 pc ){
	__register &reg = vm.spreg( REG_TOOGLE(1) );
	__register &othis = vm.spreg( REG_TOOGLE(0) );
	__register &r11 = vm.spreg( REG_TOOGLE(11) );

	if( pc==1 ) {
		((ostring*)regobject(r11))->set_string(
			((ostring*)regobject(othis))->str() + ((ostring*)regobject(reg))->str() );
	}else if( pc==5 ){
		// get to_string result
		__register &r10 = vm.spreg( REG_TOOGLE(10) );
		// concat it to this
		std::stringstream ss; ss << regobject(reg);
		((ostring*)regobject(r11))->set_string( 
				((ostring*)regobject(othis))->str() +
				((ostring*)regobject(r10))->str() );
	}

	return 1; // pc++
}

void string_addition( vm_class &lib_class ){
	corelib::uint32 idx;

	if( !lib_class.get_method_idx( "op_1_addition", idx ) ){
		std::cout << "can't get string addition operand" << std::endl;
		return;
	}

	method *m_string_addition = lib_class.get_method( idx );

	// allocate memory
	if(	!m_string_addition->set_stack_frame_size( 1, 0 ) ){
		std::cout << "error allocating string addition operand memory" << std::endl;
		return;
	}

	m_string_addition->set_flags(paper::FLG_MTHD_STATIC);
	m_string_addition->set_cpp_handler(&string_addition_hnd);
	m_string_addition->add_inst_b(paper::OP_NEW,11,lib_class.idx());
	m_string_addition->add_inst_b(paper::OP_CPPCODE,0,0);
	m_string_addition->add_inst_b(paper::OP_RETURN,11,0);
	m_string_addition->add_inst_a(paper::OP_LOADARG,0,1,0);
	m_string_addition->add_inst_b(paper::OP_UCCALL,1,0);
	m_string_addition->add_inst_b(paper::OP_CPPCODE,0,0);
	m_string_addition->add_inst_b(paper::OP_RETURN,11,0);
}

/****************************************************************** 
 * corelib.core.Array
 ******************************************************************/


/****************************************************************** 
 * corelib.core.IBuffer
 ******************************************************************/


/****************************************************************** 
 * corelib.core.RBuffer
 ******************************************************************/


/****************************************************************** 
 * corelib.core.BBuffer
 ******************************************************************/


/****************************************************************************************
 * loads debug class
 ****************************************************************************************/
void load_core_header( vmachine &vm ){
	/****************************************************************** 
	 * corelib.core.Object
	 ******************************************************************/
	corelib::pair<paper::vm_class*, bool> testc;
	testc = vm.add_class("corelib.core.Object");
	// check addition
	if(!testc.second){ return; }

	/****************************************************************** 
	 * corelib.core.String
	 ******************************************************************/
	testc = vm.add_class("corelib.core.String");
	// check addition
	if(!testc.second){ return; }

	testc.first->add_method("","cnstr_1_");
	testc.first->add_method("addition","op_1_");

	/****************************************************************** 
	 * corelib.core.Array
	 ******************************************************************/

	testc = vm.add_class("corelib.core.Array");
	// check addition
	if(!testc.second){ return; }

	/****************************************************************** 
	 * corelib.core.IBuffer
	 ******************************************************************/

	testc = vm.add_class("corelib.core.IBuffer");
	// check addition
	if(!testc.second){ return; }

	/****************************************************************** 
	 * corelib.core.RBuffer
	 ******************************************************************/

	testc = vm.add_class("corelib.core.RBuffer");
	// check addition
	if(!testc.second){ return; }

	/****************************************************************** 
	 * corelib.core.BBuffer
	 ******************************************************************/

	testc = vm.add_class("corelib.core.BBuffer");
	// check addition
	if(!testc.second){ return; }
}

void load_core_lib( vmachine &vm ){
	vm_class *lib_class = vm.get_class("corelib.core.String").first;
	// string methods
	string_cnstr( *lib_class );
	string_addition( *lib_class );
}

}; // namespace paper;

